function root
%%2022-06-26 发布华农第一版，基本完成全部功能！！见SVN

        clc
        close all
        addpath('F:\华农水稻\数种子');
        datapath = 'F:\华农水稻\root2\data\';
        
        datapath = 'F:\华农水稻\root2\data\202220709_根长芽长图片及数据\220709New\';%2022华农反馈的图片
        
        imgName = '257-1';
%         imgName = '257-2';
%         imgName = '257-3';
        imgName = '258-1';
%         imgName = '259-1';
        imgName = '259-2';
% % %         imgName = '259-3';
        imgName = '259-4';%%有重叠
%         imgName = '259-5';%%有重叠
        imgName = '275-1';%%最难样本，种与芽深度混在一起
%         imgName = '51-2';%%     (可能有重叠)
%         imgName = '51-3';
% %         imgName = '55-1';
%         imgName = '55-2';
% % %         imgName = '55-3';
% % % % % % % % % % % 
% %         imgName = '7.2-1-2';
% %         imgName = '7.2-2-1-1'; %%有须， 用Step 3e 搞定，后来增大腐蚀半径，可以在step 1处理
%         imgName = '7.2-2-2';   %%有须， 用Step 3e 搞定
% %         imgName = '7.2-2-3';   %%有须， 用Step 3e 搞定  %% 问题最多图片
%         imgName = '7.2-2-5';  %%有须，但被step 1去除
% %         imgName = '7.2-3-1';  %% Seed有分区域，在 step 3c处理
% %         imgName = '7.2-3-4-第二行';  %%弱种
% %         imgName = '7.2-4-1'; %% Seed有分区域，在 step 3c处理
% %         imgName = '7.2-4-3-第二行';  %% seed-bud 不分
% %         imgName = '排序方向7.2-1';
% %         imgName = '排序方向7.2-3-2-';



        xlsName = [imgName, '.xlsx'];        
        imgFile = getExistFile(imgName, datapath)
% % % % % % % % % % % % % % % % %      
        xlsName = '根.xlsx';  
        
        saveBWName = [datapath, 'save\BW_', imgName, '.mat'];
        saveCenterName = [datapath, 'save\center_', imgName, '.mat'];
        saveRootBudName = [datapath, 'save\root_bud_', imgName, '.mat'];
        saveImgPath = [datapath, 'saveimg\'];
        saveDataPath = [datapath, 'save\'];
         
        args.bShow = true;
%         args.bShow = false;
% % % % % % % % % % % % % % % % 批量处理方法 % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
        
        batch = true;%%批处理运行
% %         batch = false;
        if batch == true
            args.bShow = false
            
            imds = imageDatastore(datapath, 'FileExtensions',{'.jpg'}, 'IncludeSubfolders', false);
            args.saveOrg = true;%%保存第一步的图片
            args.saveOrg = false;
            
            DoLoadAllData(imds, datapath, xlsName, saveImgPath, saveDataPath, args)
            disp('done');
            return;
        end
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %         
        
% % % % % %     Step 1: OK 找出图像的内部 四边形二值化区域 % % % % % % % % % % % % % % % % % % % % % % % %
% %     [BW, img8] = DoImageEdges(imgFile, args);%%并且把图像横放
% %     save(saveBWName, 'BW', 'img8');
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %    
% % % % % % % % %     Step 2：OK 找到4个角点与中心点，然后进行投影变换，得到内部校正的矩形区域 % % % % % % 
% %     [Jproj, mmPerPixel] = DoConnersAndImage(saveBWName, args);
% %     if numel(Jproj) == 0
% %         return;
% %     end
% % 
% %     save(saveCenterName, 'Jproj', 'mmPerPixel');
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %    
% % % % %     Step 3：OK % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
    args.saveImage = true;%%保存中间结果图片
    args.saveImage = false;
    args.ImgName = imgName;%%2022-01-13
    args.DataPath = datapath;%%2022-01-13
    args.XlsName = xlsName;

    args.bSaveRatio = true;%%2022-08-02, Seed-root-bud 统计直方图
    args.bSaveRatio = false;
    args.bSaveNumber = true;%%2022-08-02， 用作种子号码顺序显示，测试用
    args.bSaveNumber = false;
% 
    [BWWs, mmPerPixel] = DoRootImage(saveCenterName, args);
    BWs.lenS = BWWs.lenS;
    BWs.boxes = BWWs.boxes;
    BWs.BW = BWWs.BW;
    BWs.BWrootMajor = BWWs.BWrootMajor;
    BWs.BWbudNew = BWWs.BWbudNew;
    BWs.BWseedNew = BWWs.BWseedNew;
    BWs.mmPerPixel = mmPerPixel;
    BWs.originRoot = BWWs.originRoot;
    BWs.BWbud2root = BWWs.BWbud2root;
    save(saveRootBudName, 'BWs');
    
% % % % %   Step 4: % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %    

%     %%args.saveExcel = true;
    args.saveExcel = false;
    args.saveCenterName = saveCenterName;
    
    args.saveFinal = true;%%2022-08-02
    args.saveFinal = false;%%2022-08-02
    
    
    data = DoCalcRootBudLength(saveRootBudName, args);
    
    disp('done');

end
%%%最新批量处理代码
function DoLoadAllData(imds, datapath, xlsName, saveImgPath, saveDataPath, args)
    
    step1 = 1;      step2 = 2;     step3 = 4;       step4 = 8;
    step5 = 16;     step6 = 32;    step7 = 128;     step8 = 256;

    step = 0;
% % %     step = step + step1;%%
% % %     step = step + step2;%%
% %     step = step + step3;%%      
    
    step = step + step4;%%
%     step = step + step5;%%
%     step = step + step6;%%

    if bitand(step, step1)     
        disp('Step 1. ...............');
        for i = 1 : length(imds.Files)  
            disp([num2str(i), '__', imds.Files{i}]);
            
            imgFile = imds.Files{i};
            [~,imgName,~] = fileparts(imgFile);
            
            [BW, img8] = DoImageEdges(imgFile, args);%%并且把图像横放
            
            saveBWName = [saveDataPath, 'BW_', imgName, '.mat'];
            save(saveBWName, 'BW', 'img8');
        end
    end
    %%Step 2：OK 找到4个角点与中心点，然后进行投影变换，得到内部校正的矩形区域
    if bitand(step, step2)     
        disp('Step 2. ...............'); 
        for i = 1 : length(imds.Files)  
            disp([num2str(i), '__', imds.Files{i}]);
            
            imgFile = imds.Files{i};
            [~,imgName,~] = fileparts(imgFile);            
               
            saveBWName = [saveDataPath, 'BW_', imgName, '.mat'];
            args.bShow = false;
            args.bShow = true;
            [Jproj, mmPerPixel] = DoConnersAndImage(saveBWName, args);
            
            if numel(Jproj) == 0
                disp(['error in', imgName]);
                continue;
            end
            
            saveCenterName = [saveDataPath, 'center_', imgName, '.mat'];
            save(saveCenterName, 'Jproj', 'mmPerPixel');
        end
    end
    
    %% Step 3:
    args.saveImage = true;%%保存中间结果图片
%     args.saveImage = false;

    args.DataPath = datapath;%%2022-01-13
    args.XlsName = xlsName;
    args.bSaveRatio = true;%%对应step 3e:的 seed-root-bud的统计
    args.bSaveRatio = false;
    args.bSaveNumber = true;%%2022-08-02 对应step 3f：种子序号重排序
%     args.bSaveNumber = false;
    
    if bitand(step, step3)     
        disp('Step 3. ...............'); 
        for i = 1 : length(imds.Files)  
            disp([num2str(i), '__', imds.Files{i}]);
            close all
            
            imgFile = imds.Files{i};
            [~,imgName,~] = fileparts(imgFile);    

            args.ImgName = imgName;%%2022-01-13
            

            saveCenterName = [saveDataPath, 'center_', imgName, '.mat'];
            close all
            [BWWs, mmPerPixel] = DoRootImage(saveCenterName, args);
            
            continue;%%暂时，方便存储 中间处理图片
            
            BWs.lenS = BWWs.lenS;
            BWs.boxes = BWWs.boxes;
            BWs.BW = BWWs.BW;
            BWs.BWrootMajor = BWWs.BWrootMajor;
            BWs.BWbudNew = BWWs.BWbudNew;
            BWs.BWseedNew = BWWs.BWseedNew;
            BWs.mmPerPixel = mmPerPixel;
            BWs.originRoot = BWWs.originRoot;
            BWs.BWbud2root = BWWs.BWbud2root;
            
            saveRootBudName = [saveDataPath, 'root_bud_', imgName, '.mat'];
            save(saveRootBudName, 'BWs');
            
            if isfield(BWs, 'fig')
                saveStep3ImgName = [saveImgPath, 'save\step3_', imgName, '.png']; 
                figure(fig);
                f = MyHelper.GetAFrame();
                imwrite(f.cdata, saveStep3ImgName);
            end
        end
    end
    %% Step 4:    
    if bitand(step, step4) 
        args.saveExcel = true;
        args.saveExcel = false;
        args.saveFinal = true;%%2022-08-02
        % % args.saveFinal = false;%%2022-08-02
        disp('Step 4. ...............'); 
        for i = 1 : length(imds.Files)  
            disp([num2str(i), '__', imds.Files{i}]);
            close all
            
            imgFile = imds.Files{i};
            [~,imgName,~] = fileparts(imgFile);    

            args.ImgName = imgName;%%2022-01-13

            saveRootBudName = [saveDataPath, 'root_bud_', imgName, '.mat'];
            args.saveCenterName = [saveDataPath, 'center_', imgName, '.mat'];
            args.saveFinalResult = [datapath, 'saveimg\final\', imgName, '.jpg'];
            
            [~, figBud, figRoot, figAll] = DoCalcRootBudLength(saveRootBudName, args);
            
                % % % % % %
            saveBudImgName = [saveImgPath, 'ske_bud_', imgName, '.png'];
            figure(figBud);
            DetailHelper.SaveFigure2Img(saveBudImgName);

            saveRootImgName = [saveImgPath, 'ske_root_', imgName, '.png']; 
            figure(figRoot);
            DetailHelper.SaveFigure2Img(saveRootImgName);

            saveImgAllName = [saveImgPath, 'img_', imgName, '.png']; 
            figure(figAll);
            DetailHelper.SaveFigure2Img(saveImgAllName);
            
        end
    end
    
    %% Step 6:
    if bitand(step, step6)     
        disp('Step 6. ...............'); 
        mmPerPixels = zeros(length(imds.Files), 1);
        for i = 1 : length(imds.Files)  
            disp([num2str(i), '__', imds.Files{i}]);
            
            
            imgFile = imds.Files{i};
            [~,imgName,~] = fileparts(imgFile);    

            args.ImgName = imgName;%%2022-01-13

            saveRootBudName = [saveDataPath, 'root_bud_', imgName, '.mat'];
            data = load(saveRootBudName, 'BWs');
            BWs = data.BWs;
            args.mmPerPixel = BWs.mmPerPixel;
            
            
            mmPerPixels(i) = args.mmPerPixel;
            args.mmPerPixel
        end
        format long g
        mmPerPixels
        format short g
    end
    
    
end



%%% 得到图片文件
function imgFile = getExistFile(imgName, datapath)
    imgFile = [datapath, imgName, '.jpg'];
    if exist(imgFile,'file') == 2
        return;
    end
    imgFile = [datapath, imgName, '.png'];
    if exist(imgFile,'file') == 2
        return;
    end
    imgFile = [datapath, imgName, '.tif'];
    if exist(imgFile,'file') == 2
        return;
    end
    imgFile = 'nofile';    
end

function colID = getColId(name)  
    names{1}='51-2';
    names{2}='51-3';
    names{3}='55-1';
    names{4}='55-2';
    names{5}='55-3';
    names{6}='257-1';
    names{7}='257-2';
    names{8}='257-3';
    names{9}='258-1';
    names{10}='259-1';
    names{11}='259-2';
    names{12}='259-3';
    names{13}='259-4';
    names{14}='259-5';
    names{15}='275-1';
    for i = 1 : length(names)
        if strcmp(names{i}, name) == true
            colID = i*2;
            return;
        end
    end
end

%% Step 4: 具体计算根和芽的长度
function [data, figBud, figRoot, figAll] = DoCalcRootBudLength(saveRootBudName, args)

    data = load(args.saveCenterName, 'Jproj', 'mmPerPixel');
    mmPerPixel = data.mmPerPixel;
    img8 = data.Jproj;%%%%加载图片
    
    data = load(saveRootBudName, 'BWs');
    BWs = data.BWs;
    
    args.mmPerPixel = BWs.mmPerPixel;
    args.bShow = true;
    args.img8 = img8;%%%
    
    [data, figBud, figRoot, figAll] = RootHelper.calcRootBudLength(BWs, args);
    
    dataBud = data.budLength;
    dataRoot = data.rootLength;
    lenS = BWs.lenS;
    
    datapath = args.DataPath;
    xlsName = args.XlsName;%%Excel文件
    imgName = args.ImgName;


    
    if args.saveExcel == true
        col = getColId(imgName);%%列iD
        colChar = GetColChar(col);%%列的字符

        rowStart = 14;
        
        try
            dataAll = [dataRoot, dataBud];    
            xlswrite([datapath, xlsName], dataAll, 'Sheet2', [colChar, num2str(rowStart)])
        catch ME        
            disp(ME.message)
            [dataRoot, dataBud]
        end
    end
end
%%计算Excel 的col对应的字母列名
function colChar = GetColChar(col)
    ascA = abs('A');
    if col <= 26
        colChar = char(ascA + col - 1);
    else
        times = floor((col-1) / 26);
        ret = mod(col-1, 26) +1;
        colChar1 = char(ascA + times - 1);
        colChar2 = char(ascA + ret - 1);
        colChar = [colChar1, colChar2];
    end
end



%% Step 3:
function [BWs, mmPerPixel] = DoRootImage(saveCenterName, args)
    data = load(saveCenterName, 'Jproj', 'mmPerPixel');
    mmPerPixel = data.mmPerPixel;
    img8 = data.Jproj;
    
% % %     args.bShow = true;%%显示中间结果
    args.fileSaveCCC = [args.DataPath, 'saveimg\thresh\ccc_', args.ImgName, '.png'];
    args.fileSaveRRR = [args.DataPath, 'saveimg\thresh\rrr_', args.ImgName, '.png'];
    args.fileSaveAAA = [args.DataPath, 'saveimg\thresh\aaa_', args.ImgName, '.png'];
    args.fileSaveBBB = [args.DataPath, 'saveimg\thresh\bbb_', args.ImgName, '.png'];

    args.fileSaveCC2 = [args.DataPath, 'saveimg\twoTh\ccc_', args.ImgName, '.png'];
    args.fileSaveRR2 = [args.DataPath, 'saveimg\twoTh\rrr_', args.ImgName, '.png'];
    args.fileSaveAA2 = [args.DataPath, 'saveimg\twoTh\aaa_', args.ImgName, '.png'];
    args.fileSaveBB2 = [args.DataPath, 'saveimg\twoTh\bbb_', args.ImgName, '.png'];
    
    args.fileSaveCCH = [args.DataPath, 'saveimg\hist\ccc_', args.ImgName, '.png'];
    args.fileSaveRRH = [args.DataPath, 'saveimg\hist\rrr_', args.ImgName, '.png'];
    args.fileSaveAAH = [args.DataPath, 'saveimg\hist\aaa_', args.ImgName, '.png'];
    args.fileSaveBBH = [args.DataPath, 'saveimg\hist\bbb_', args.ImgName, '.png'];
    
    args.fileSaveCCI = [args.DataPath, 'saveimg\img\ccc_', args.ImgName, '.png'];
    args.fileSaveRRI = [args.DataPath, 'saveimg\img\rrr_', args.ImgName, '.png'];
    args.fileSaveAAI = [args.DataPath, 'saveimg\img\aaa_', args.ImgName, '.png'];
    args.fileSaveBBI = [args.DataPath, 'saveimg\img\bbb_', args.ImgName, '.png'];
    
    args.fileSaveCCCPPP = [args.DataPath, 'saveimg\img\pcc_', args.ImgName, '.png'];
    
    args.fileSaveRatio = [args.DataPath, 'saveimg\ratio\', args.ImgName, '.txt'];%%中间测试用    
    args.fileSaveNumber = [args.DataPath, 'saveimg\number\', args.ImgName, '.jpg'];%% 中间测试用
    args.saveFinalResult = [args.DataPath, 'saveimg\final\', args.ImgName, '.jpg'];%% 中间测试用;%%2022-08-02
    args.mmPerPixel = mmPerPixel;
    
    BWs = RootHelper.ExtractRoots(img8, args);    
end
%% Step 1:
function [BW, img8] = DoImageEdges(imgFile, args)
    img8 = imread(imgFile);
   
    
    img8 = imguidedfilter(img8);%%导向滤波
    [height, width, ~] = size(img8);
    if (height > width)
        img8 = imrotate(img8, 90);
    end
    
    
    lab = double(rgb2lab(img8));  
    lll = lab(:, :, 1);
% %     aaa = lab(:, :, 2);
% %     bbb = lab(:, :, 3);   
% %     
% % %     ycr = double(rgb2ycbcr(img8));
% % %     yyy = ycr(:, :, 1);
% %     ccc = ycr(:, :, 2);
% %     rrr = ycr(:, :, 3);
    
% %     bShow = true;
    bShow = args.bShow;
    BW = Helper.findInnerRegion(lll, bShow);   
% %     BW = Helper.findInnerRegion(yyy, bShow);
end

%% Step 2:
function [Jproj, mmPerPixel] = DoConnersAndImage(saveBWName, args)
    data = load(saveBWName, 'BW', 'img8');
    BW = data.BW;
    img8 = data.img8;
    
% %     bShow = true;
    bShow = args.bShow;
    [Jproj, ptLoc, distM, ratio, mmPerPixel] = Helper.findConnersAndImage(BW, img8, bShow);
    
    ptLoc
    ratio    
end


